﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using System.Reflection;
using CNative.WebApi.Utils;
using CNative.WebApi.Common;
using CNative.WebApi.ServiceProcess;

namespace CNative.WebApiHost
{
    public static class MyProgram
    {
        #region API
        [DllImport("User32.dll ", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll ", EntryPoint = "GetSystemMenu")]
        extern static IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert);
        [DllImport("user32.dll ", EntryPoint = "RemoveMenu")]
        extern static int RemoveMenu(IntPtr hMenu, int nPos, int flags);
        #endregion

        #region 关闭按钮禁用
        /// <summary>
        /// 关闭按钮禁用
        /// </summary>
        public static void RemoveCLOSE_MENU()
        {
            try
            {
                //与控制台标题名一样的路径            
                string fullPath = Assembly.GetEntryAssembly().Location;
                //根据控制台标题找控制台            
                int WINDOW_HANDLER = FindWindow(null, fullPath);
                //找关闭按钮            
                IntPtr CLOSE_MENU = GetSystemMenu((IntPtr)WINDOW_HANDLER, IntPtr.Zero);
                int SC_CLOSE = 0xF060;
                //关闭按钮禁用            
                RemoveMenu(CLOSE_MENU, SC_CLOSE, 0x0);
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.TargetSite + "\n" + ex.StackTrace + "\n" + ex.Message);
            }
        }
        #endregion
        #region var
        /// <summary>
        /// 系统用于标志此服务名称(唯一性)
        /// </summary>
        public static string ServiceName = "CNative.WebApiHost";
        /// <summary>
        /// 向用户标志服务的显示名称(可以重复)
        /// </summary>
        public static string DisplayName = "CNative.WebApiHost";
        /// <summary>
        /// 服务的说明(描述)
        /// </summary>
        public static string Description = "接口服务";
        /// <summary>
        /// 服务依赖，多个以“;”分隔
        /// </summary>
        public static string DependedOn = "";
        #endregion
        #region Init
        public static void Init()
        {
            try
            {
                using (var setting = new MyConfig())
                {
                    //系统用于标志此服务名称(唯一性)
                    MyProgram.ServiceName = setting.ServiceName;
                    //向用户标志服务的显示名称(可以重复)
                    MyProgram.DisplayName = setting.DisplayName;
                    //服务的说明(描述)
                    MyProgram.Description = setting.Description;
                    // 服务依赖，多个以“;”分隔
                    MyProgram.DependedOn = setting.DependedOn;
                }
            }
            catch (Exception ex)
            {
                LogUtil.Error(ex.TargetSite + "\n" + ex.StackTrace + "\n" + ex.Message);
            }
        }
        #endregion
        #region 安装服务/卸载服务
        /// <summary>
        /// 安装服务/卸载服务
        /// </summary>
        /// <param name="args"></param>
        public static void InstallOrUninstallServerce(string[] args, IBootstrap bootstrap)
        {
            if (args != null && args.Length > 0)
            {
                var flag = args[0].Trim();
               // var ss = Assembly.GetEntryAssembly().Location;
                var ServiceName = Assembly.GetEntryAssembly().Location; //Funs.GetFilePath(System.Reflection.Assembly.GetExecutingAssembly().Location);
                //ServiceName = Funs.PathCombine(ServiceName,Funs.GetAppSettingsVal(ServiceName,""));//只到程序名称，不带.exe
                //ServiceName = ServiceName.Substring(0, ServiceName.LastIndexOf('.'));
                if (flag.ToLower() == "InstallmyService".ToLower() || flag.ToLower() == "-i".ToLower() || flag.ToLower() == "i".ToLower())
                {
                    var ret = SelfInstaller.InstallMe();
                    //var ret = ServiceAPI.InstallService(ServiceName);
                    LogUtil.Debug("InstallService " + ServiceName + " is " + ret);
                }
                else if (flag.ToLower() == "UnInstallmyService".ToLower() || flag.ToLower() == "-u".ToLower() || flag.ToLower() == "u".ToLower())
                {
                    var ret = SelfInstaller.UninstallMe();
                    //var ret = ServiceAPI.UninstallService(ServiceName);
                    LogUtil.Debug("UninstallService " + ServiceName + " is " + ret);
                }
                else if (flag.ToLower() == "run".ToLower() || flag.ToLower() == "-r".ToLower() || flag.ToLower() == "r".ToLower())
                {
                    RunAsConsole(bootstrap, null);
                }
                //else
                //{
                //    var ret = ServiceAPI.UninstallService(ServiceName);
                //    LogUtil.Debug("UninstallService2 " + ServiceName + " is " + ret);
                //}
            }
        }
        #endregion
        #region 应用程序的主入口点
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        public static void MyMain(IBootstrap bootstrap, Action ShowConfigInfo)
        {
            if ((!Environment.UserInteractive)//Windows Service
                )
            {
                LogUtil.Info("Main,Run as in Service ,!Environment.UserInteractive");
                RunAsService(bootstrap);
                return;
            }
            //获取欲启动进程名  
            string strProcessName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
            //检查进程是否已经启动，已经启动则显示报错信息退出程序。 
            var pr = System.Diagnostics.Process.GetProcessesByName(strProcessName);
            if (pr.Length > 1)
            {
                //System.Windows.Forms.MessageBox.Show("程序已经运行");
                LogUtil.Error("程序已经运行");
                System.Environment.Exit(0);
            }
            else
            {
                RemoveCLOSE_MENU();
                LogUtil.Info("Main,Run as in Console ");

                var sc = new MyServiceController(Assembly.GetEntryAssembly().Location);
                sc.RefreshServiceStatus();
               
                string exeArg = string.Empty;
                var logo = @"                               __                         
                              /\ \                        
 __  __  __    ___     ___    \_\ \     __   _ __   ____  
/\ \/\ \/\ \  / __`\ /' _ `\  /'_` \  /'__`\/\`'__\/',__\ 
\ \ \_/ \_/ \/\ \L\ \/\ \/\ \/\ \L\ \/\  __/\ \ \//\__, `\
 \ \___x___/'\ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/
  \/__//__/   \/___/  \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ 
                                                          
                                                          ";
                LogUtil.WriteText(logo, ConsoleColor.Green);
                LogUtil.WriteText("欢迎进入" + Description, ConsoleColor.White);

                LogUtil.WriteText("请输入[r,i,u]其中一个字符，继续...", ConsoleColor.White);
                LogUtil.WriteText("-[r]: 输入\"r\" 在控制台中运行本服务", ConsoleColor.White);
                if (sc.IsInstallted == false)
                    LogUtil.WriteText("-[i]: 输入\"i\" 安装本服务到 Windows Service 中", ConsoleColor.White);
                else
                    LogUtil.WriteText("-[u]: 输入\"u\" 从 Windows Service 中卸载本服务", ConsoleColor.White);
                LogUtil.WriteText("5秒后，将自动在控制台中运行本服务", ConsoleColor.Red);

                var t = new System.Timers.Timer(5000);
                t.Enabled = true;
                t.Elapsed += (sender, e) =>
                {
                    t.Enabled = false;
                    Console.Clear();
                    RunAsConsole(bootstrap, ShowConfigInfo);
                };
                while (t.Enabled)
                {
                    exeArg = Console.ReadKey().KeyChar.ToString();
                                                //Console.WriteLine();
                    //LogUtil.Debug($"exeArg={exeArg}");
                    if (Run(exeArg, bootstrap, ShowConfigInfo, t))
                        break;
                }
                // RunAsConsole(bootstrap, ShowConfigInfo);
            }
        }
        private static bool Run(string exeArg, IBootstrap bootstrap, Action ShowConfigInfo,System.Timers.Timer t)
        {
            switch (exeArg.ToLower())
            {
                case ("-i"):
                case ("i"):
                    t.Enabled = false;
                    Console.Clear();
                    SelfInstaller.InstallMe();
                    //InstallOrUninstallServerce(new string[] { "i" });
                    return true;

                case ("-u"):
                case ("u"):
                    t.Enabled = false;
                    Console.Clear();
                    SelfInstaller.UninstallMe();
                    //InstallOrUninstallServerce(new string[] { "u" });
                    return true;

                case ("-r"):
                case ("r"):
                    t.Enabled = false;
                    RunAsConsole(bootstrap, ShowConfigInfo);
                    return true;
                default:
                    return false;
            }
        }
        public static void RunAsService(IBootstrap bootstrap)
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
			{ 
				new Service(bootstrap) 
			};
            ServiceBase.Run(ServicesToRun);
        }

        public static void RunAsConsole(IBootstrap bootstrap, Action ShowConfigInfo)
        {
            //RemoveCLOSE_MENU();
            Console.Clear();
            var logo = @"                          _               
                         | |              
 __      _____  _ __   __| | ___ _ __ ___ 
 \ \ /\ / / _ \| '_ \ / _` |/ _ \ '__/ __|
  \ V  V / (_) | | | | (_| |  __/ |  \__ \
   \_/\_/ \___/|_| |_|\__,_|\___|_|  |___/
                                          
                                          ";
            LogUtil.WriteText(logo, ConsoleColor.DarkGreen);
            Console.WriteLine("------------欢迎进入【" + Description + "】------------");
            Console.WriteLine("...");
            //Console.WriteLine("初始化...");
            //Console.WriteLine("开始...");
            bootstrap.Start();

            LogUtil.WriteLinetext();
            LogUtil.WriteText(string.Format("- {0} 已经启动", Description), ConsoleColor.Green);
            LogUtil.WriteLinetext();

            //SetConsoleColor(ConsoleColor.White);
            //Console.WriteLine("- 系统配置信息：");
            //Console.WriteLine("------执行间隔：{0}{1}", (bootstrap.ConfigBase.TimeType == 2 ? bootstrap.ConfigBase.IntervalTime / (60 * 60) : (bootstrap.ConfigBase.TimeType == 1 ? bootstrap.ConfigBase.IntervalTime / 60 : bootstrap.ConfigBase.IntervalTime))
            //                                        , (bootstrap.ConfigBase.TimeType == 2 ? "小时" : (bootstrap.ConfigBase.TimeType == 1 ? "分钟" : "秒")));

            if (ShowConfigInfo != null)
            {
                ShowConfigInfo();
            }
            LogUtil.WriteLinetext();

            Console.ResetColor();
            Console.WriteLine("输入 'quit' 或者 'q' 退出系统.");

            var line = Console.ReadLine();
            while (true)
            {
                if ("q".Equals(line, StringComparison.OrdinalIgnoreCase) || "quit".Equals(line, StringComparison.OrdinalIgnoreCase))
                    break;
                else
                    line = Console.ReadLine();
            }
            bootstrap.Stop();

            Console.WriteLine(Description + "已经停止!");
        }   
        #endregion
    }
    #region SelfInstaller
    public static class SelfInstaller
    {
        private static readonly string _exePath = Assembly.GetEntryAssembly().Location;

        public static bool InstallMe()
        {
            try
            {
                System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { _exePath });
            }
            catch
            {
                return false;
            }
            return true;
        }

        public static bool UninstallMe()
        {
            try
            {
                System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { "/u", _exePath });
            }
            catch
            {
                return false;
            }
            return true;
        }

        #region 启动服务
        ///// <summary>  
        ///// 启动服务  
        ///// </summary>  
        ///// <param name=" NameService ">服务名</param>  
        ///// <returns>存在返回 true,否则返回 false;</returns>  
        public static bool StartService(string serviceName)
        {
            bool flag = true;
            try
            {
               // if (isServiceIsExisted(serviceName))
                {
                    System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
                    if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending)
                    {
                        service.Start();
                        TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 10);
                        service.WaitForStatus(ServiceControllerStatus.Running, timeout);
                        //Funs.SleepFunc(() =>
                        //{
                        //    service.Refresh();
                        //    return service.Status == System.ServiceProcess.ServiceControllerStatus.Running;
                        //});
                    }
                }
            }
            catch (Exception ex)
            {
                flag = false;
                LogUtil.Error(ex.ToString());
            }
            return flag;
        }
        #endregion

        #region 停止服务
        ///// <summary>  
        ///// 停止服务  
        ///// </summary>  
        ///// <param name=" NameService ">服务名</param>  
        ///// <returns>存在返回 true,否则返回 false;</returns>  
        public static bool StopService(string serviceName)
        {
            bool flag = true;
            try
            {
               // if (isServiceIsExisted(serviceName))
                {
                    System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
                    if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                    {
                        service.Stop();
                        TimeSpan timeout = TimeSpan.FromMilliseconds(1000 * 10);
                        service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
                        //Funs.SleepFunc(() =>
                        //{
                        //    service.Refresh();
                        //    return service.Status == System.ServiceProcess.ServiceControllerStatus.Stopped;
                        //});
                    }
                }
            }
            catch (Exception ex)
            {
                flag = false;
                LogUtil.Error(ex.ToString());
            }
            return flag;
        }
        #endregion    
    }
    #endregion
}
